﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Departure
{
    class ExceptionHandling
    {
        #region Exception Messages Overloads
        public static string ConstructFullExceptionChainString(Exception ex)
        {
            StringBuilder sb = new StringBuilder();
            ConstructFullExceptionChainString(ex, sb, true);
            return sb.ToString();
        }
        /// <summary>
        /// Doesn't include stack
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        public static string ConstructExceptionChainString(Exception ex)
        {
            StringBuilder sb = new StringBuilder();
            ConstructFullExceptionChainString(ex, sb, false);
            return sb.ToString();
        }
        public static string ConstructFullExceptionChainString(Exception ex, bool includeStackTrace)
        {
            StringBuilder sb = new StringBuilder();
            ConstructFullExceptionChainString(ex, sb, includeStackTrace);
            return sb.ToString();
        }
        /// <summary>
        /// Includes stack
        /// </summary>
        /// <param name="exs"></param>
        /// <returns></returns>
        public static string ConstructFullExceptionChainString(IEnumerable<Exception> exs)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Exception ex in exs)
            {
                ConstructFullExceptionChainString(ex, sb, true);
                sb.AppendLine();
            }
            return sb.ToString();
        }
        /// <summary>
        /// Doesn't include stack
        /// </summary>
        /// <param name="exs"></param>
        /// <returns></returns>
        public static string ConstructExceptionChainString(IEnumerable<Exception> exs)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Exception ex in exs)
            {
                ConstructFullExceptionChainString(ex, sb, false);
                sb.AppendLine();
            }
            return sb.ToString();
        }
        public static void ConstructFullExceptionChainString(Exception ex, StringBuilder sb)
        {
            ConstructFullExceptionChainString(ex, sb, true);
        }
        public static void ConstructFullExceptionChainString(Exception ex, StringBuilder sb, bool includeStackTrace)
        {
            if (ex != null)
            {
                AppendExcpetionDetails(ex, sb, includeStackTrace, 1);

                if (ex.InnerException != null)
                {
                    BuildExceptionChain(ex.InnerException, sb, 1, includeStackTrace);
                }
            }
        }
        private static void BuildExceptionChain(Exception ex, StringBuilder sb, int levelDeep, bool includeStackTrace)
        {
            sb.AppendLine();
            for (int i = 0; i < levelDeep; i++)
            {
                sb.AppendFormat("\t");
            }

            sb.Append("Caused by: ");
            AppendExcpetionDetails(ex, sb, includeStackTrace, levelDeep);

            if (ex.InnerException != null)
            {
                BuildExceptionChain(ex.InnerException, sb, levelDeep + 1, includeStackTrace);
            }
        }
        private static void AppendExcpetionDetails(Exception ex, StringBuilder sb, bool includeStackTrace, int curLevelDeep)
        {
            sb.Append(ex.Message);

            if (includeStackTrace)
            {
                sb.AppendLine();
                sb.AppendLine(ex.StackTrace);
            }
        }
        #endregion

        public class NoDeparturesException : Exception
        {
            public NoDeparturesException()
            {
                
            }

            public NoDeparturesException(string Message)
            {
                this.message = Message;
            }

            string message;
            public override string Message 
            {
                get
                {
                    return message;
                }
            }
            
        }
    }
}
